package cn.zn.quartz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.zn.base.common.constant.ScheduleConstants;
import cn.zn.quartz.dto.JobDto;
import cn.zn.quartz.dto.JobLogDto;
import cn.zn.quartz.mapper.JobMapper;
import cn.zn.quartz.service.JobService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class JobServiceImpl implements JobService {

    private static final Logger log = LoggerFactory.getLogger(JobServiceImpl.class);

    @Autowired
    private Scheduler scheduler;

    @Autowired
    private JobMapper jobMapper;

    @Override
    public void initJobs() throws Exception {
        scheduler.clear();
        List<JobDto> jobList = jobMapper.selectJobList();
        createScheduleJobs(jobList);
    }

    @Override
    public void createScheduleJobs(List<JobDto> jobs) throws Exception {
        if (CollUtil.isNotEmpty(jobs)) {
            for (JobDto job : jobs) {
                try {
                    createScheduleJob(job);
                } catch (Exception e) {
                    log.error("创建任务错误：任务名：" + job.getJobName() + "，错误内容：" + e.toString());
                }
            }
        }
    }

    @Override
    public void createScheduleJob(JobDto job) throws Exception {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        //构建job信息
        JobDetail jobDetail = JobBuilder.newJob(getClass(job.getInvokeTarget()).getClass()).withIdentity(jobKey).build();
        jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
        //表达式调度构建器(即任务执行的时间)
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        //按新的cronExpression表达式构建一个新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
        scheduler.scheduleJob(jobDetail, trigger);
        // 启动调度器
        if (scheduler.isShutdown()) {
            scheduler.start();
        }
        if ("1".equals(job.getStatus())) {
            scheduler.pauseJob(jobKey);
        }
    }

    @Override
    public void pauseJob(JobDto job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        scheduler.pauseJob(jobKey);
    }

    @Override
    public void resumeJob(JobDto job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        scheduler.resumeJob(jobKey);
    }

    @Override
    public void deleteJob(JobDto job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        scheduler.deleteJob(jobKey);
    }

    @Override
    public void run(JobDto job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        scheduler.triggerJob(jobKey);
    }

    @Override
    public void updateJob(JobDto job) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(), job.getJobGroup());
        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 按新的cronExpression表达式重新构建trigger
        trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

        // 按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, trigger);

        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
        if ("1".equals(job.getStatus())) {
            scheduler.pauseJob(jobKey);
        }
    }

    @Override
    @Transactional
    public void insertJobLog(JobLogDto log) {
        log.setId(IdUtil.fastSimpleUUID());
        jobMapper.insertJobLog(log);
    }

    private Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }
}
